﻿package com.hutra.utils {
	
	final public class Number3D extends Object {
		private var vy:Number;
		private var num:Number3D;
		private var mod:Number;
		private var vx:Number;
		private var _scale:Number;
		private var vz:Number;
		private const MathPI:Number = 3.14159;
		private var dist:Number;
		public var x:Number;
		public var y:Number;
		public var z:Number;
		public static var BACKWARD:Number3D = new Number3D(0, 0, -1);
		public static var FORWARD:Number3D = new Number3D(0, 0, 1);
		public static var LEFT:Number3D = new Number3D(-1, 0, 0);
		public static var DOWN:Number3D = new Number3D(0, -1, 0);
		public static var UP:Number3D = new Number3D(0, 1, 0);
		public static var RIGHT:Number3D = new Number3D(1, 0, 0);
		
		public function Number3D(param1:Number = 0, param2:Number = 0, param3:Number = 0, param4:Number = 1, param5:Boolean = false) {
			this.x = param1;
			this.y = param2;
			this.z = param3;
			this._scale = param4;
			if (param5) {
				normalize();
			}
			return;
		} // end function
		
		public function sub(param1:Number3D, param2:Number3D):void {
			x = param1.x - param2.x;
			y = param1.y - param2.y;
			z = param1.z - param2.z;
			return;
		} // end function
		
		public function distanceinXYPlane(param1:Number3D):Number {
			var _loc_2:* = Math.sqrt(Math.pow(param1.y - y, 2) + Math.pow(param1.x - x, 2));
			return _loc_2;
		} // end function
		
		public function cross(param1:Number3D, param2:Number3D):void {
			if (param1 == this || param2 == this) {
				throw new Error("resultant cross product cannot be the same instance as an input");
			}
			x = param2.y * param1.z - param2.z * param1.y;
			y = param2.z * param1.x - param2.x * param1.z;
			z = param2.x * param1.y - param2.y * param1.x;
			return;
		} // end function
		
		public function get scale():Number {
			return _scale;
		} // end function
		
		public function dot(param1:Number3D):Number {
			return x * param1.x + y * param1.y + z * param1.z;
		} // end function
		
		public function getXYAngle(param1:Number3D):Number {
			var _loc_2:Number = 0;
			_loc_2 = Math.acos(Math.abs(param1.x - x) / distance(param1)) * 180 / Math.PI;
			return _loc_2;
		} // end function
		
		public function closestPointOnPlane(param1:Number3D, param2:Number3D, param3:Number3D):Number3D {
			if (!num) {
				num = new Number3D();
			}
			num.sub(param1, param2);
			dist = param3.dot(num);
			num.scaleNumberBy(param3, dist);
			num.sub(param1, num);
			return num;
		} // end function
		
		public function interpolate(param1:Number3D, param2:Number):void {
			var _loc_3:* = new Number3D();
			_loc_3.sub(param1, this);
			_loc_3.scaleNumberBy(_loc_3, param2);
			add(this, _loc_3);
			return;
		} // end function
		
		public function set scale(param1:Number):void {
			_scale = param1;
			return;
		} // end function
		
		public function clone(param1:Number3D):void {
			x = param1.x;
			y = param1.y;
			z = param1.z;
			return;
		} // end function
		
		public function getAngle(param1:Number3D = null):Number {
			if (param1 == null) {
				param1 = new Number3D();
			}
			return Math.acos(dot(param1) / (modulo * param1.modulo));
		} // end function
		
		public function normalize(param1:Number = 1):void {
			mod = modulo / param1;
			if (mod != 0 && mod != 1) {
				x = x / mod;
				y = y / mod;
				z = z / mod;
			}
			return;
		} // end function
		
		public function add(param1:Number3D, param2:Number3D):void {
			x = param1.x + param2.x;
			y = param1.y + param2.y;
			z = param1.z + param2.z;
			return;
		} // end function
		
		public function scaleNumberBy(param1:Number3D, param2:Number):void {
			x = param1.x * param2;
			y = param1.y * param2;
			z = param1.z * param2;
			return;
		} // end function
		
		public function toString():String {
			return "x:" + x + " y:" + y + " z:" + z;
		} // end function
		
		public function distance(param1:Number3D):Number {
			return Math.sqrt((x - param1.x) * (x - param1.x) + (y - param1.y) * (y - param1.y) + (z - param1.z) * (z - param1.z));
		} // end function
		
		public function get modulo():Number {
			return Math.sqrt(x * x + y * y + z * z);
		} // end function
		
		public function get modulo2():Number {
			return x * x + y * y + z * z;
		} // end function
		
		public function equals(param1:Number3D):Boolean {
			return param1.x == x && param1.y == y && param1.z == z;
		} // end function
		
		public static function getInterpolated(param1:Number3D, param2:Number3D, param3:Number):Number3D {
			var _loc_4:* = new Number3D();
			_loc_4.sub(param1, param2);
			_loc_4.scaleNumberBy(_loc_4, param3);
			_loc_4.add(_loc_4, param2);
			return _loc_4;
		} // end function
	
	}
}
